﻿using System;
using System.Collections.Generic;
using System.Text;

namespace PhantomChainsAnalyser.Model
{
    public class Sampling
    {
        private List<double> Values = null;//выборка
        private List<double> Ranged = null;

        public Sampling()
        {
            Values = new List<double>();
            Ranged = new List<double>();
        }

        private Sampling(List<double> values)
        {
            Values = values;
            Ranged = values;
        }

        /// <summary>
        /// возвращает значение по индексу
        /// </summary>
        /// <param name="Number"></param>
        /// <returns></returns>
        public double GetValue(int Number)
        {
            return Values[Number];
        }

        /// <summary>
        /// добавляет значение в выборку
        /// </summary>
        /// <param name="value"></param>

        public void AddValue(double value)
        {
            Values.Add(value);
            AddToRanged(value);

        }

        /// <summary>
        /// возвращает объём выборки
        /// </summary>
        /// <returns></returns>
        public int GetVolume()
        {
            return Values.Count;
        }

        /// <summary>
        /// возвращает среднее значение в выборке
        /// </summary>
        /// <returns></returns>
        public double AvеrageValue()
        {
            double Sum = 0;
            for (int i = 0; i < GetVolume(); i++)
            {
                Sum += GetValue(i);
            }
            return Sum / GetVolume();
        }

        /// <summary>
        /// возвращает упорядоченную по возрастанию выборку
        /// </summary>
        /// <returns></returns>
        public Sampling RangedSampling()
        {
            Sampling mass = new Sampling(Ranged);
            return mass;
        }

        /// <summary>
        /// удаляет значение из выборки
        /// </summary>
        /// <param name="value"></param>
        public void DeletValue(double value)
        {
            Values.Remove(value);
            Ranged.Remove(value);
        }

        /// <summary>
        /// возвращает минимальное значение в выборке
        /// </summary>
        /// <returns></returns>
        public double Min()
        {
            return Ranged[0];
        }

        /// <summary>
        /// возвращает максимальное значение в выборке
        /// </summary>
        /// <returns></returns>
        public double Max()
        {
            return Ranged[Ranged.Count - 1];
        }

        /// <summary>
        /// возвращает копию выборки
        /// </summary>
        /// <returns></returns>
        public Sampling Clone()
        {
            Sampling Result = new Sampling();
            for (int i = 0; i < GetVolume(); i++)
            {
                Result.AddValue(GetValue(i));
            }
            return Result;
        }

        /// <summary>
        /// устанавливает значение в i-ю позицию выборки
        /// </summary>
        /// <param name="position"></param>
        /// <param name="value"></param>
        public void SetValue(int position, double value)
        {
            Ranged.Remove(Values[position]);
            AddToRanged(value);
            Values[position] = value;
        }

        public double this[int index]
        {
            get { return Values[index]; }
            set { SetValue(index, value); }
        }

        private void AddToRanged(double value)
        {
            Ranged.Add(double.MaxValue);
            double Temp1 = value;
            double Temp2;
            for (int i = 0; i < Ranged.Count; i++)
            {
                if (Ranged[i] > value)
                {
                    Temp2 = Ranged[i];
                    Ranged[i] = Temp1;
                    Temp1 = Temp2;
                }
            }
        }

        public double MeanSquareDeviation()
        {
            return Math.Sqrt(Dispersion());
        }

        public double Dispersion()
        {
            double D = 0;
            double AverageValue = AvеrageValue();
            for (int i = 0; i < Ranged.Count; i++)
            {
                D += Math.Pow((Ranged[i] - AverageValue), 2)*((double)1/Ranged.Count);
            }
            return D;
        }
    }
}